using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Abp.Authorization.Users;
using Abp.Domain.Services;
using Abp.IdentityFramework;
using Abp.Runtime.Session;
using Abp.UI;
using Vecen.BangChuang.Authorization.Roles;
using Vecen.BangChuang.MultiTenancy;
using Microsoft.AspNetCore.Identity;
using Vecen.BangChuang.BangChuang.Common;
using Vecen.BangChuang.BangChuang.DomainServices.Common;

namespace Vecen.BangChuang.Authorization.Users {
    public class UserRegistrationManager: DomainService {
        public IAbpSession AbpSession { get; set; }

        private readonly TenantManager _tenantManager;
        private readonly UserManager _userManager;
        private readonly RoleManager _roleManager;
        private readonly IPasswordHasher<User> _passwordHasher;
        private readonly ValidationCodeDomainService _validationCodeDomainService;

        public UserRegistrationManager(TenantManager tenantManager,
            UserManager userManager,
            RoleManager roleManager,
            IPasswordHasher<User> passwordHasher,
            ValidationCodeDomainService validationCodeDomainService) {
            _tenantManager = tenantManager;
            _userManager = userManager;
            _roleManager = roleManager;
            _passwordHasher = passwordHasher;
            _validationCodeDomainService = validationCodeDomainService;

            AbpSession = NullAbpSession.Instance;
        }

        /// <summary>
        /// 用户名和邮箱注册
        /// </summary>
        /// <param name="name">名</param>
        /// <param name="surname">姓</param>
        /// <param name="emailAddress">邮箱地址</param>
        /// <param name="userName">用户名</param>
        /// <param name="plainPassword">密码</param>
        /// <param name="isEmailConfirmed">邮箱是否已确认</param>
        /// <returns></returns>
        public async Task<User> RegisterAsync(string name,
            string surname,
            string emailAddress,
            string userName,
            string plainPassword,
            bool isEmailConfirmed) {
            CheckForTenant();

            var tenant = await GetActiveTenantAsync();

            var user = new User {
                TenantId = tenant.Id, Name = name, Surname = surname, EmailAddress = emailAddress, IsActive = true,
                UserName = userName, IsEmailConfirmed = true, Roles = new List<UserRole>()
            };

            user.SetNormalizedNames();

            user.Password = _passwordHasher.HashPassword(user, plainPassword);
            var roles = await Task.Run(() => {
                return _roleManager.Roles.Where(r => r.IsDefault).ToList();
            });
            foreach(var defaultRole in roles) {
                user.Roles.Add(new UserRole(tenant.Id, user.Id, defaultRole.Id));
            }

            CheckErrors(await _userManager.CreateAsync(user));
            await CurrentUnitOfWork.SaveChangesAsync();
            return user;
        }

        /// <summary>
        /// 通过手机号注册
        /// </summary>
        /// <param name="phoneNumber"></param>
        /// <param name="validationCode"></param>
        /// <param name="plainPassword"></param>
        /// <returns></returns>
        public async Task<User> RegisterAsync(string phoneNumber, string validationCode, string plainPassword) {
            if(!await _validationCodeDomainService.ValidationAsync(phoneNumber, validationCode,
                ValidationCodeType.Register)) {
                throw new UserFriendlyException("请求失败!", "验证码不正确!");
            }
            CheckForTenant();
            var tenant = await GetActiveTenantAsync();
            var user = new User {
                TenantId = tenant.Id, PhoneNumber = phoneNumber, IsActive = true, IsPhoneNumberConfirmed = true,
                Roles = new List<UserRole>(), UserName = Guid.NewGuid().ToString()
            };

            user.Password = _passwordHasher.HashPassword(user, plainPassword);
            var roles = await Task.Run(() => {
                return _roleManager.Roles.Where(r => r.IsDefault).ToList();
            });
            foreach(var defaultRole in roles) {
                user.Roles.Add(new UserRole(tenant.Id, user.Id, defaultRole.Id));
            }

            CheckErrors(await _userManager.CreateAsync(user));
            await CurrentUnitOfWork.SaveChangesAsync();
            return user;
        }

        private void CheckForTenant() {
            if(!AbpSession.TenantId.HasValue) {
                throw new InvalidOperationException("Can not register host users!");
            }
        }

        private async Task<Tenant> GetActiveTenantAsync() {
            if(!AbpSession.TenantId.HasValue) {
                return null;
            }

            return await GetActiveTenantAsync(AbpSession.TenantId.Value);
        }

        private async Task<Tenant> GetActiveTenantAsync(int tenantId) {
            var tenant = await _tenantManager.FindByIdAsync(tenantId);
            if(tenant == null) {
                throw new UserFriendlyException("请求失败!", L("UnknownTenantId{0}", tenantId));
            }

            if(!tenant.IsActive) {
                throw new UserFriendlyException("请求失败!", L("TenantIdIsNotActive{0}", tenantId));
            }

            return tenant;
        }

        protected virtual void CheckErrors(IdentityResult identityResult) {
            identityResult.CheckErrors(LocalizationManager);
        }
    }
}